#include "imageview.h"
#include <qpainter.h>
#include <QMouseEvent>
#include <QBrush>
#include <QDebug>
#include <QPixmap>
#include <QMenu>
#include <QTimer>
#include <QApplication>
#include <QClipboard>
#include "pubdef.h"
#include "ppocr/ocr_pub.h"
#include "ner/bertinfer.h"
#include <QShortcut>
#include <QDesktopServices>
#include <regex> // For std::regex_replace


ImageView::~ImageView()
{
    printf("delete image view\n");
}
ImageView::ImageView(QWidget *parent)
    : QWidget{parent}
{
    m_isCal = false;
    m_wheelFlag = false;

    m_timer = new QTimer();
    connect(m_timer,SIGNAL(timeout()),this,SLOT(timerTimeOut()));//用槽函数控制扫描效果。
    m_linkAction = new QActionGroup(nullptr);
    m_mailAction = new QActionGroup(nullptr);;
    m_nameAction = new QActionGroup(nullptr);;
    m_addressAction = new QActionGroup(nullptr);;
    m_positionAction = new QActionGroup(nullptr);;
    m_phoneNumberAction = new QActionGroup(nullptr);;

}

void ImageView::calcAndShow()
{
    if(m_isCal)
    {
        return;
    }
    if (!m_img.isNull())
    {
        m_isCal = true;
        int srcWidth = m_img.width();
        int srcHeight = m_img.height();
        printf("srcWidth: %d, srcHeight: %d", srcWidth, srcHeight);

        int curWinWidth = this->width();
        int curWinHeight = this->height();
        printf("curWinWidth: %d, curWinHeight: %d", curWinWidth, curWinHeight);
        //        qDebug() << "curWinWidth: " << curWinWidth << ", curWinHeight: " << curWinHeight;

        if (srcHeight / srcWidth > curWinHeight / curWinWidth)
        {
            m_newHeight = curWinHeight;
            m_newWidth = srcWidth * curWinHeight / srcHeight;
            m_scale = (float)m_newWidth / (float)srcWidth;
        }
        else
        {
            m_newHeight = srcHeight * curWinWidth / srcWidth;
            m_newWidth = curWinWidth;
            m_scale = (float)m_newWidth / (float)srcWidth;
        }
        qDebug() << "m_newWidth: " << m_newWidth << ", m_newHeight: " << m_newHeight;
        m_point = QPoint(int((curWinWidth - m_newWidth) * 0.5), int((curWinHeight - m_newHeight) * 0.5));
        qDebug() << "m_scale: " << m_scale << "m_point: " << m_point.x() << " " << m_point.y();
        //        update();

        startOCR();
    }
}
//void ImageView::ocrImage()
//{


//    std::vector<OCRPredictResult> ocr_result = ocr_file(m_srcPath.toStdString().c_str());

//    int minX, minY, maxX, maxY;
//    m_cutBoxSet.clear();
//    for (int i = 0; i < ocr_result.size(); i++) {
//        std::vector<std::vector<int>> boxes = ocr_result[i].box;
//        if (boxes.size() > 0)
//        {
//            for (int n = 0; n < boxes.size(); n++) {
//                if(n==0)
//                {
//                    minX = boxes[n][0];
//                    minY = boxes[n][1];
//                    maxX = boxes[n][0];
//                    maxY = boxes[n][1];
//                }
//                else
//                {
//                    if(boxes[n][0]<minX)
//                    {
//                        minX = boxes[n][0];
//                    }
//                    else if(boxes[n][0]>maxX)
//                    {
//                        maxX = boxes[n][0];
//                    }
//                    if(boxes[n][1]<minY)
//                    {
//                        minY = boxes[n][0];
//                    }
//                    else if(boxes[n][1]>maxY)
//                    {
//                        maxY = boxes[n][1];
//                    }
//                }
//            }

//        }
//        m_cutBoxSet.append(TextBox(QRect(minX,minY,maxX-minX,maxY-minY),QString::fromStdString(ocr_result[i].text)));
//    }

//    m_width = m_srcImg.width();
//    m_height = m_srcImg.height();

//    QImage imageDeepen = processing::pictureCutDeepen(m_srcImg.toImage(), m_srcImg.size());   //给图片加上蒙层
//    QImage image = m_srcImg.toImage();                                                     //无蒙层原图


//    for (int i = 0; i < m_cutBoxSet.length(); i++) {
//        for (int j = m_cutBoxSet.at(i).rect.top(); j < m_cutBoxSet.at(i).rect.bottom() ; j++) {
//            for (int k = m_cutBoxSet.at(i).rect.left(); k < m_cutBoxSet.at(i).rect.right() ; k++) {
//                QColor color(image.pixelColor(k, j));
//                imageDeepen.setPixel(k, j, color.rgb());
//            }
//        }
//    }


//    m_img = QPixmap::fromImage(imageDeepen);
//    calcAndShow();
//}

void ImageView::getText()
{
    m_text = "";
    for (int i = 0; i < m_cutBoxSet.count(); i++)
    {
        m_text.append(m_cutBoxSet.at(i).text);
        if(m_cutBoxSet.at(i).flag == 1)
        {
            m_text.append(" ");
        }
        else if(m_cutBoxSet.at(i).flag == 2)
        {
            m_text.append("\n");
        }
    }
}
void ImageView::createRightMenu()
{
    if(m_rightMenu)
    {
        m_rightMenu->deleteLater();
    }
    m_rightMenu = new QMenu();
    m_copyAction = m_rightMenu->addAction("Copy");
    m_copyAllAction = m_rightMenu->addAction("CopyAll");
    m_selectAllAction = m_rightMenu->addAction("Select All");

    if(m_grepResult.size())
    {
        m_isSeparatorAdded = true;
        m_rightMenu->addSeparator();

        auto it = m_grepResult.find("link");
        if (it != m_grepResult.end()) {
            std::vector<std::string> links = it->second;
            if(links.size()>=1)
            {
                QMenu *linkMenu = m_rightMenu->addMenu("link");
                for (const std::string& link : links)
                {
                    linkMenu->addAction(QString::fromStdString(link))->setActionGroup(m_linkAction);
                }
            }
//            else
//            {
//                m_rightMenu->addAction(QString::fromStdString(links.at(0)))->setActionGroup(m_linkAction);
//            }
        }

        it = m_grepResult.find("email");
        if (it !=m_grepResult.end()) {
            std::vector<std::string> links = it->second;
            if(links.size()>=1)
            {
                QMenu *linkMenu = m_rightMenu->addMenu("email");
                for (const std::string& link : links)
                {
                    linkMenu->addAction(QString::fromStdString(link))->setActionGroup(m_mailAction);
                }
            }
//            else
//            {
//                m_rightMenu->addAction(QString::fromStdString(links.at(0)))->setActionGroup(m_mailAction);
//            }
        }
    }
    connect(m_rightMenu, &QMenu::triggered, this, &ImageView::triggerMenu);
    new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_C), this, SLOT(copySelectText()));
    new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C), this, SLOT(copyAllText()));
    new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_A), this, SLOT(selectAll()));
}
void ImageView::appendRightMenu()
{

    if(m_nerResult.size())
    {
        if(!m_isSeparatorAdded)
        {
            m_rightMenu->addSeparator();
        }

        QMap<QString, QStringList>::iterator it;
        for (it = m_nerResult.begin(); it != m_nerResult.end(); ++it)
        {
            if(it.key() == "link" || it.key() == "email")
            {
                continue;
            }
            const QStringList& list = it.value();
            if(list.size()>=1)
            {
                QMenu *linkMenu = m_rightMenu->addMenu(it.key());
                for (const QString& value : list) {
                    linkMenu->addAction(value);
                }
            }
        }
    }

}

void ImageView::getLinkAndMail()
{
    m_grepResult.clear();
    std::string input = m_text.toStdString();
//    std::string input = "我叫王五，您可以发邮件至个人邮箱wangwu@qq.com 联系我。我来自广州市天河区，现在是一名软件工程师。工作请联络李靖童，工作邮箱panxiaofengstudio@163.com 我的手机号码是13267436701，主页是www.panxiao.com, 请你一定要来湖南省衡阳市珠晖区这边来看看，还有http://ddcom.com，我叫文六小，您可以发邮件至个人邮箱:wangffwu@qq.com 联系我。我来自长沙市开福区，现在是一名硬件工程师。工作请联络李空童，工作邮箱：panxiaofsssengstudio@126.com";
    // 正则表达式用于匹配以http、https或ftp开头的URL
    //    std::regex url_regex("\\b(?:(https?|ftp|file)://|www\\.)\\S+\\b");
    std::regex url_regex("\\b(?:(https?|ftp|file)://|www\\.)[-A-Za-z0-9+&@#/%?=~_|!:,.;]+\\b");
    // R"((http|https|ftp)://[^\s]+)"
    // \\b(?:(https?|ftp|file)://|www\\.)[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]
    // 使用标准库中的sregex_iterator进行正则表达式搜索
    //
    auto urls_begin = std::sregex_iterator(input.begin(), input.end(), url_regex);
    auto urls_end = std::sregex_iterator();

    // 遍历所有匹配结果并输出
    for (std::sregex_iterator i = urls_begin; i != urls_end; ++i) {
        std::smatch match = *i;
        std::string match_str = match.str();
        std::cout << "Found URL: " << match_str << std::endl;
        m_grepResult["link"].push_back(match_str);
    }


    std::regex mail_regex("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b");
    auto mail_begin = std::sregex_iterator(input.begin(), input.end(), mail_regex);
    auto mail_end = std::sregex_iterator();

    // 遍历所有匹配结果并输出
    for (std::sregex_iterator i = mail_begin; i != mail_end; ++i) {
        std::smatch match = *i;
        std::string match_str = match.str();
        std::cout << "Found Mail: " << match_str << std::endl;
        m_grepResult["email"].push_back(match_str);
    }

}


void ImageView::nerTextFinished(int result)
{
    m_nerResult = m_nerThread->nerResult();
    appendRightMenu();
}

void ImageView::ocrImageFinished(int result)
{
    m_img = m_ocrThread->outImage();
    m_cutBoxSet = m_ocrThread->cutBoxSets();
    m_lineSet = m_ocrThread->lineSets();
    m_lineTopSet = m_ocrThread->lineTopSets();
    m_timer->stop();
    m_viewMode = IdleMode;
    update();
    getText();
    getLinkAndMail();
    createRightMenu();
    startNER();
}


void ImageView::timerTimeOut()
{
    m_timerIndex++;
    if(m_timerIndex>100)
    {
        m_timerIndex = 1;

        m_direction = 0-m_direction;
    }
    if(m_direction == 1)
    {
        m_scanRect = QRect(m_point, QSize(m_width*m_scale,m_height*m_scale*m_timerIndex*0.01));
    }
    else
    {
        m_scanRect = QRect(QPoint(m_point.x(), m_point.y()+m_height*m_scale*(100-m_timerIndex)*0.01), QSize(m_width*m_scale,m_height*m_scale*m_timerIndex*0.01));
    }
    update();
}

void ImageView::setImage(QString imgPath)
{
    m_isPixmap = false;
    m_srcPath = imgPath;
    m_srcImg = QPixmap(m_srcPath);
    m_img = m_srcImg;
    m_width = m_srcImg.width();
    m_height = m_srcImg.height();

    m_viewMode = IdleMode;

    m_isCal = false;
    repaint();
    //    calcAndShow();
    //    startOCR();
}
void ImageView::setPixmap(QPixmap pixmap)
{
    m_isPixmap = true;
    m_srcPath = "";
    m_srcImg = pixmap;
    m_img = m_srcImg;

    m_width = m_srcImg.width();
    m_height = m_srcImg.height();
    m_viewMode = IdleMode;
    m_isCal = false;
    repaint();
    //    calcAndShow();
    //    startOCR();
}
void ImageView::startNER()
{
    printf("ImageView::startOCR");
    m_nerResult.clear();

    if(m_nerThread != nullptr)
    {
        m_nerThread->setCancel();
        if(m_nerThread->isRunning())
        {
            m_nerThread->quit();
        }
        for (int i = 0; i < m_nerThreads.length(); i++) {
            if(m_nerThreads.at(i)->isFinished())
            {

                NERThread *thread = m_nerThreads.at(i);
                m_nerThreads.removeOne(thread);
                thread->disconnect();
                thread->deleteLater();
            }
        }

    }

    m_nerThread = new NERThread();
    m_nerThreads.append(m_nerThread);
    connect(m_nerThread, SIGNAL(returnNerResult(int)), this, SLOT(nerTextFinished(int)));


    m_nerThread->setInputText(m_text.toStdString());

    m_nerThread->start();
}

void ImageView::startOCR()
{
    printf("ImageView::startOCR");
    m_cutBoxSet = QList<TextBox>();
    //    bool createThread = true;
    if(m_ocrThread != nullptr)
    {
        m_ocrThread->setCancel();
        if(m_ocrThread->isRunning())
        {
            m_ocrThread->quit();
        }
        for (int i = 0; i < m_ocrThreads.length(); i++) {
            if(m_ocrThreads.at(i)->isFinished())
            {

                OCRThread *thread = m_ocrThreads.at(i);
                m_ocrThreads.removeOne(thread);
                thread->disconnect();
                thread->deleteLater();
            }
        }

    }

    m_ocrThread = new OCRThread();
    m_ocrThreads.append(m_ocrThread);
    connect(m_ocrThread, SIGNAL(returnResult(int)), this, SLOT(ocrImageFinished(int)));


    m_ocrThread->setInputImage(m_srcPath, &m_srcImg);



    m_viewMode = LoadMode;
    m_timerIndex = 1;
    m_direction = 1;
    m_timer->start(20);
    m_ocrThread->start();
}



void ImageView::wheelEvent(QWheelEvent *event)
{
    float angleY = event->delta()/8;
    m_lastScale = m_scale;
    m_wheelFlag = true;
    // 获取当前鼠标相对于view的位置
    m_x = event->x();
    m_y = event->y();
    if (angleY > 0)
    {
        m_scale *= 1.08;
    }
    else  //滚轮下滚
    {
        m_scale *= 0.92;
    }

    if (m_scale < 0.1)
    {
        m_scale = 0.1;
    }
    else if (m_scale > 100)
    {
        m_scale = 100;
    }

    adjustSize();
    update();
}
void ImageView::drawSingleCharOutlineAndLine(QPainter &painter)
{

    painter.setPen(QPen(Qt::NoPen));//去掉外框线
    for (int i = 0; i < m_cutBoxSet.length(); i++)
    {
        QVector<float> poslist = m_cutBoxSet.at(i).poslist;
        QVector<float> widthlist = m_cutBoxSet.at(i).widthlist;
        //        printf("draw box%d: ", i);
        //        qDebug() << m_cutBoxSet.at(i).text;
        //        printf("\n");
        for(int k=0;k<poslist.size();k++)
        {
            painter.setBrush(QBrush(QColor(rand()%256, rand()%256, rand()%256, 128)));
            QRect rect = QRect(QPoint(m_point.x()+(m_cutBoxSet.at(i).rect.left()+poslist.at(k))*m_scale, m_point.y()+m_cutBoxSet.at(i).rect.top()*m_scale), QSize(widthlist.at(k)*m_scale, m_cutBoxSet.at(i).rect.size().height()*m_scale));
            //            printf("%f, %f; ", poslist.at(k), widthlist.at(k));
            painter.drawRect(rect);
        }
        //        printf("\n");

    }
    //draw line
    for(int k=0;k<m_lineSet.size();k++)
    {
        painter.setBrush(QBrush(QColor(255, 0, 0, 128)));
        QRect rect = QRect(0, m_point.y()+m_lineSet.at(k)*m_scale, 800, 1);
        //            printf("%f, %f; ", poslist.at(k), widthlist.at(k));
        painter.drawRect(rect);
    }
    //draw line
    for(int k=0;k<m_lineTopSet.size();k++)
    {
        painter.setBrush(QBrush(QColor(0, 255, 0, 128)));
        QRect rect = QRect(0, m_point.y()+m_lineTopSet.at(k)*m_scale, 800, 1);
        //            printf("%f, %f; ", poslist.at(k), widthlist.at(k));
        painter.drawRect(rect);
    }



}

void ImageView::drawScanner(QPainter &painter)
{
    QLinearGradient linearGradient;
    if(m_direction == 1)
    {
        linearGradient = QLinearGradient(QPointF(m_scanRect.left()+m_scanRect.width()/2, m_scanRect.top()+m_scanRect.height()),QPointF(m_scanRect.left()+m_scanRect.width()/2, m_scanRect.top()));
    }
    else
    {
        linearGradient = QLinearGradient(QPointF(m_scanRect.left()+m_scanRect.width()/2, m_scanRect.top()), QPointF(m_scanRect.left()+m_scanRect.width()/2, m_scanRect.top()+m_scanRect.height()));
    }
    //插入颜色
    linearGradient.setColorAt(0, QColor(117, 184, 245,200));
    linearGradient.setColorAt(0.03, QColor(117, 184, 245,50));
    //    linearGradient.setColorAt(0.05, QColor(117, 184, 245,50));
    //    linearGradient.setColorAt(0.03, QColor(117, 184, 245,190));
    linearGradient.setColorAt(0.5, QColor(117, 184, 245,10));
    linearGradient.setColorAt(1, QColor(117, 184, 245,10));
    //指定渐变区域以外的区域的扩散方式
    linearGradient.setSpread(QGradient::PadSpread);
    //使用渐变作为画刷

    painter.setBrush(linearGradient);
    painter.setPen(QPen(Qt::NoPen));//去掉外框线
    QRect rect = QRect(m_scanRect.topLeft(),QSize(m_scanRect.width(),m_scanRect.height()));
    painter.drawRect(rect);
}
void ImageView::drawSelection(QPainter &painter)
{
#ifdef QT_DEBUG
    //            printf("draw selection\n");
#endif


    painter.setBrush(QBrush(QColor(0, 0, 255, 128)));
    painter.setPen(QPen(Qt::NoPen));//去掉外框线
    float pos1 = 0;
    float pos2 = 0;
    int start = m_s1<m_s2?m_s1:m_s2;
    int end = m_s1<m_s2?m_s2:m_s1;
    if(m_s1==m_s2)
    {
        pos1 = m_s1_pos<m_s2_pos?m_s1_pos:m_s2_pos;
        pos2 = m_s1_pos<m_s2_pos?m_s2_pos:m_s1_pos;
    }
    else
    {
        pos1 = m_s1<m_s2?m_s1_pos:m_s2_pos;
        pos2 = m_s1<m_s2?m_s2_pos:m_s1_pos;
    }
#ifdef QT_DEBUG
    //    printf("s1: %d, s2: %d\n", m_s1, m_s2);
    //    printf("pos1: %f, pos2: %f\n", m_s1_pos, m_s2_pos);
#endif
    for (int i = start; i <= end; i++)
    {
        QRect rect= QRect();
        double offsetStart = -1;
        double endWidth = -1;
        if(i==start && i==end)
        {
            QVector<float> poslist = m_cutBoxSet.at(i).poslist;
            int j = 1;
            for(;j<poslist.size();j++)
            {
                if(pos1<poslist.at(j))
                {
                    break;
                }
            }
            if(poslist.size()==0)
            {
                offsetStart = 0;
                j = 1;
            }
            else
            {
                offsetStart = poslist.at(j-1);
            }

            //end
            int k = poslist.size()-1;
            for(;k>-1;k--)
            {
                if(pos2>poslist.at(k))
                {
                    break;
                }
            }

            if(k==poslist.size()-1)
            {
                endWidth = m_cutBoxSet.at(i).rect.size().width();
            }
            else
            {
                endWidth = poslist.at(k+1);
            }


            if(offsetStart!=-1 && endWidth!=-1)
            {
                QRect rect = QRect(QPoint(m_point.x()+(m_cutBoxSet.at(i).rect.left()+offsetStart)*m_scale, m_point.y()+m_cutBoxSet.at(i).rect.top()*m_scale), QSize((endWidth-offsetStart)*m_scale, m_cutBoxSet.at(i).rect.size().height()*m_scale));
                painter.drawRect(rect);
            }

        }
        else if(i==start)
        {
            QVector<float> poslist = m_cutBoxSet.at(i).poslist;
            endWidth = m_cutBoxSet.at(i).rect.size().width();
            int j = 1;
            for(;j<poslist.size();j++)
            {
                if(pos1<poslist.at(j))
                {
                    break;
                }
            }
            if(poslist.size()==0)
            {
                offsetStart = 0;
                j = 1;
            }
            else
            {
                offsetStart = poslist.at(j-1);
            }

            if(offsetStart!=-1 && endWidth!=-1)
            {
                QRect rect = QRect(QPoint(m_point.x()+(m_cutBoxSet.at(i).rect.left()+offsetStart)*m_scale, m_point.y()+m_cutBoxSet.at(i).rect.top()*m_scale), QSize((endWidth-offsetStart)*m_scale, m_cutBoxSet.at(i).rect.size().height()*m_scale));
                painter.drawRect(rect);
            }
        }
        else if(i==end)
        {
            QVector<float> poslist = m_cutBoxSet.at(i).poslist;
            offsetStart = 0;
            int k = poslist.size()-1;
            for(;k>-1;k--)
            {
                if(pos2>poslist.at(k))
                {
                    break;
                }
            }

            if(k==poslist.size()-1)
            {
                endWidth = m_cutBoxSet.at(i).rect.size().width();
            }
            else
            {
                endWidth = poslist.at(k+1);
            }

            if(offsetStart!=-1 && endWidth!=-1)
            {
                QRect rect = QRect(QPoint(m_point.x()+(m_cutBoxSet.at(i).rect.left()+offsetStart)*m_scale, m_point.y()+m_cutBoxSet.at(i).rect.top()*m_scale), QSize((endWidth-offsetStart)*m_scale, m_cutBoxSet.at(i).rect.size().height()*m_scale));
                painter.drawRect(rect);
            }


        }
        else
        {
            QRect rect = QRect(QPoint(m_point.x()+m_cutBoxSet.at(i).rect.left()*m_scale, m_point.y()+m_cutBoxSet.at(i).rect.top()*m_scale), QSize(m_cutBoxSet.at(i).rect.size().width()*m_scale, m_cutBoxSet.at(i).rect.size().height()*m_scale));
            painter.drawRect(rect);
        }

    }
}

void ImageView::paintEvent(QPaintEvent *event)
{
    //    printf("ImageView paintEvent");


    if (!m_img.isNull())
    {
        calcAndShow();
        //        printf("!m_img.isNull()");
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        if (m_wheelFlag)       // 定点缩放
        {
            m_wheelFlag = false;
            m_point = QPoint(m_x-(m_x-m_point.x())/m_lastScale*m_scale, m_y+(m_point.y()-m_y)/m_lastScale*m_scale);
        }
#ifdef QT_DEBUG
        //        qDebug() << "---m_scale: " << m_scale << "m_point: " << m_point.x() << " " << m_point.y()  << "realPoint: " << m_lastPos.x() << " " << m_lastPos.y();
#endif
        //通过自己计算图像位置，更加精准

        painter.drawPixmap(QRect(m_point, QSize(m_width*m_scale,m_height*m_scale)), m_img, QRect(0, 0, m_width, m_height));


        if(m_viewMode == TextMode)
        {
            drawSelection(painter);
        }
        else if(m_viewMode == LoadMode)
        {
            drawScanner(painter);
        }
#ifdef QT_DEBUG
        //        else
        //        {
        //            drawSingleCharOutlineAndLine(painter);
        //        }
#endif
    }
}
void ImageView::selectAll()
{
    m_viewMode = TextMode;
    m_s1 = 0;
    m_s1_pos = 0;
    m_s2 = m_cutBoxSet.size()-1;
    m_s2_pos = m_cutBoxSet.at(m_s2).rect.size().width();
    repaint();
}
void ImageView::copySelectText()
{
    if(m_viewMode != TextMode)
    {
        return;
    }
    QString text;
    float pos1 = 0;
    float pos2 = 0;
    int start = m_s1<m_s2?m_s1:m_s2;
    int end = m_s1<m_s2?m_s2:m_s1;
    if(m_s1==m_s2)
    {
        pos1 = m_s1_pos<m_s2_pos?m_s1_pos:m_s2_pos;
        pos2 = m_s1_pos<m_s2_pos?m_s2_pos:m_s1_pos;
    }
    else
    {
        pos1 = m_s1<m_s2?m_s1_pos:m_s2_pos;
        pos2 = m_s1<m_s2?m_s2_pos:m_s1_pos;
    }
#ifdef QT_DEBUG
    //    printf("s1: %d, s2: %d\n", m_s1, m_s2);
    //    printf("pos1: %f, pos2: %f\n", m_s1_pos, m_s2_pos);
#endif
    for (int i = start; i <= end; i++)
    {
        QRect rect= QRect();
        double offsetStart = -1;
        double endWidth = -1;
        if(i==start && i==end)
        {
            QVector<float> poslist = m_cutBoxSet.at(i).poslist;
            int j = 1;
            for(;j<poslist.size();j++)
            {
                if(pos1<poslist.at(j))
                {
                    break;
                }
            }
            if(poslist.size()==0)
            {
                j = 1;
            }
            //end
            int k = poslist.size()-1;
            for(;k>-1;k--)
            {
                if(pos2>poslist.at(k))
                {
                    break;
                }
            }
            text.append(m_cutBoxSet.at(i).text.mid(j-1,k-j+2));
        }
        else if(i==start)
        {
            QVector<float> poslist = m_cutBoxSet.at(i).poslist;
            endWidth = m_cutBoxSet.at(i).rect.size().width();
            int j = 1;
            for(;j<poslist.size();j++)
            {
                if(pos1<poslist.at(j))
                {
                    break;
                }
            }
            if(poslist.size()==0)
            {
                j = 1;
            }
            text.append(m_cutBoxSet.at(i).text.mid(j-1,poslist.size()-j+1));
            if(m_cutBoxSet.at(i).flag == 1)
            {
                text.append(" ");
            }
            else if(m_cutBoxSet.at(i).flag == 2)
            {
                text.append("\n");
            }
        }
        else if(i==end)
        {
            QVector<float> poslist = m_cutBoxSet.at(i).poslist;

            int k = poslist.size()-1;
            for(;k>-1;k--)
            {
                if(pos2>poslist.at(k))
                {
                    break;
                }
            }
            text.append(m_cutBoxSet.at(i).text.mid(0,k+1));
        }
        else
        {
            text.append(m_cutBoxSet.at(i).text);
            if(m_cutBoxSet.at(i).flag == 1)
            {
                text.append(" ");
            }
            else if(m_cutBoxSet.at(i).flag == 2)
            {
                text.append("\n");
            }
        }

    }
    QClipboard* clip = QApplication::clipboard();
    clip->setText(text);
}

void ImageView::copyAll()
{
    QClipboard* clip = QApplication::clipboard();
    clip->setText(m_text);
}
void ImageView::triggerMenu(QAction *act)
{
    QString str = act->text();
    if (act == m_copyAction)
    {
        copySelectText();
    }
    else if (act == m_selectAllAction)
    {
        selectAll();
    }
    else if (act == m_copyAllAction)
    {
        copyAll();
    }
    else
    {
        if (act->actionGroup() == m_linkAction)
        {
            QString link = str;
            if (!link.startsWith("http://") && !link.startsWith("https://")) {
                link.prepend("http://"); // 添加 http:// 前缀
            }
            QUrl url(link);
            QDesktopServices::openUrl(url);
        }
        else if (act->actionGroup() == m_mailAction)
        {
            QString link = str;
            link.prepend("mailto:");
            QUrl url(link);
            QDesktopServices::openUrl(url);
        }
        QClipboard* clip = QApplication::clipboard();
        clip->setText(str);
    }
}
void ImageView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_leftClick = true;
        m_startPos = event->pos();
        m_lastPos = event->pos();
        if(m_viewMode == LoadMode)
        {
            //            update();
            return;
        }
        //        if(!m_isPixmap)
        //        {
        m_viewMode = DragMode;
        //        }
        // 判断当前鼠标pos在不在图上

        m_pos1 = QPoint((event->pos().x()-m_point.x())/m_scale, (event->pos().y()-m_point.y())/m_scale);
        m_pos1_line = getLineOfPos(m_pos1);
        for (int i = 0; i < m_cutBoxSet.length(); i++)
        {
            if(m_cutBoxSet.at(i).rect.contains(m_pos1))
            {
                m_viewMode = TextModeReady;
                printf("is text Mode\n");
                printf("%d, %d, %d, %d\n",m_cutBoxSet.at(i).rect.left(),
                       m_cutBoxSet.at(i).rect.top(),
                       m_cutBoxSet.at(i).rect.right(),
                       m_cutBoxSet.at(i).rect.bottom());
                printf("%s\n",m_cutBoxSet.at(i).text.toStdString().c_str());


                m_cutBoxSet[i].isSelected = true;
                m_s1 = i;
                m_s1_pos = m_pos1.x()-m_cutBoxSet.at(i).rect.left();
                printf("m_s1_pos: %f\n", m_s1_pos);
                m_line = m_cutBoxSet[i].line;
                break;
            }
        }
        if(m_viewMode == TextModeReady)
        {
            for (int k=m_s1; k >=0; k--)
            {
                m_t1 = m_cutBoxSet.at(k).rect.top();
                m_t2 = m_cutBoxSet.at(k).rect.bottom();
                if(m_cutBoxSet.at(k).line != m_line)
                {
                    break;
                }
            }
        }
#ifdef QT_DEBUG
        //        printf("pos: %d, %d, %d, %d, %d, %d\n", event->pos().x(), event->pos().y(), m_point.x(), m_point.y(), curPos.x(), curPos.y());
#endif

        update();

    }
    else if (event->button() == Qt::RightButton)
    {
        if(m_rightMenu)
        {
            m_rightMenu->popup(QCursor::pos());
        }
    }
}
void ImageView::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if(m_viewMode == LoadMode)
        {
            return;
        }
        m_leftClick = false;
        //        m_viewMode = IdleMode;
    }
}
void ImageView::mouseDoubleClickEvent(QMouseEvent *event)
{

}
bool ImageView::comprePosition()
{
    //    printf("a.y:%d,b.y:%d\n",a.y(),b.y());
    if(m_pos1.x() == m_pos2.x())
    {
        return m_pos1.y() < m_pos2.y()? true: false;
    }

    if(m_pos1_line == m_pos2_line)
    {
        //        printf("lineA == lineB\n");
        return m_pos1.x() < m_pos2.x()? true: false;
    }
    else
    {
        //        printf("lineA:%d-%d < lineB:%d-%d %d\n", lineA,lineA/2,lineB,lineB/2,lineA < lineB? true: false);
        return m_pos1_line < m_pos2_line? true: false;
    }
}
int ImageView::getLineOfPos(QPoint pos)
{
    int line = 1;
    if(m_lineSet.size()==0)
    {
        return line;
    }
    for(int i=0;i<m_lineSet.size();i++)
    {
        line++;
        if(pos.y()<=m_lineTopSet.at(i))
        {
            break;
        }
        line++;
        if(pos.y()<=m_lineSet.at(i)+LINE_TOLENRANCE)
        {
            break;
        }
    }
    if(pos.y()>m_lineSet.last()+LINE_TOLENRANCE)
    {
        line++;
    }
    return line;
}
void ImageView::processPos2WhenAsc()
{
    //    printf("Asc \n");
    m_s2 = -2;
    m_s2_pos = -2;
    bool is_in_line = m_pos2_line%2==1 ? true: false;
    int line = m_pos2_line/2;
    if(line>m_lineSet.size())
    {
        m_s2 = m_cutBoxSet.size()-1;
        m_s2_pos = m_cutBoxSet.last().rect.width();
    }
    else
    {
        if(is_in_line)
        {
            for (int i = 0; i < m_cutBoxSet.size(); i++)
            {
                if(line == m_cutBoxSet.at(i).line)
                {
                    if(m_pos2.x()<m_cutBoxSet.at(i).rect.right())
                    {
                        m_s2 = i-1;
                        break;
                    }
                    else if(m_cutBoxSet.at(i).flag == 2)
                    {
                        m_s2 = i;
                        break;
                    }
                }
            }
            if(m_s2<m_s1)
            {
                m_s2 = m_s1;
                m_s2_pos = m_pos2.x()-m_cutBoxSet.at(m_s2).rect.left();
            }
            else
            {
                m_s2_pos = m_cutBoxSet.at(m_s2).rect.width();
            }
        }
        else
        {
            for (int i = 0; i < m_cutBoxSet.size(); i++)
            {
                if(line-1 == m_cutBoxSet.at(i).line && m_cutBoxSet.at(i).flag == 2)
                {
                    //                    printf("now %d", i);
                    m_s2 = i;
                    m_s2_pos = m_cutBoxSet.at(i).rect.width();
                    return;
                }
            }
        }
    }
    if(m_s2 == -2)
    {
        m_s2 = m_s1;
        m_s2_pos = m_cutBoxSet.at(m_s2).rect.width();
        //        printf("error\n");
    }

}
void ImageView::processPos1WhenAsc()
{
    //    printf("Asc \n");
    m_s2 = -2;
    m_s2_pos = -2;
    bool is_in_line = m_pos2_line%2==1 ? true: false;
    int line = m_pos2_line/2;
    if(line>m_lineSet.size())
    {
        m_s2 = m_cutBoxSet.size()-1;
        m_s2_pos = m_cutBoxSet.last().rect.width();
    }
    else
    {
        if(is_in_line)
        {
            for (int i = 0; i < m_cutBoxSet.size(); i++)
            {
                if(line == m_cutBoxSet.at(i).line)
                {
                    if(m_pos2.x()<m_cutBoxSet.at(i).rect.right())
                    {
                        m_s2 = i-1;
                        break;
                    }
                    else if(m_cutBoxSet.at(i).flag == 2)
                    {
                        m_s2 = i;
                        break;
                    }
                }
            }
            if(m_s2<m_s1)
            {
                m_s2 = m_s1;
                m_s2_pos = m_pos2.x()-m_cutBoxSet.at(m_s2).rect.left();
            }
            else
            {
                m_s2_pos = m_cutBoxSet.at(m_s2).rect.width();
            }
        }
        else
        {
            for (int i = 0; i < m_cutBoxSet.size(); i++)
            {
                if(line-1 == m_cutBoxSet.at(i).line && m_cutBoxSet.at(i).flag == 2)
                {
                    //                    printf("now %d", i);
                    m_s2 = i;
                    m_s2_pos = m_cutBoxSet.at(i).rect.width();
                    return;
                }
            }
        }
    }
    if(m_s2 == -2)
    {
        m_s2 = m_s1;
        m_s2_pos = m_cutBoxSet.at(m_s2).rect.width();
        //        printf("error\n");
    }

}
bool ImageView::processPos2IfContained(QPoint pos2)
{
    for (int i = 0; i < m_cutBoxSet.size(); i++)
    {
        if(m_cutBoxSet.at(i).rect.contains(pos2))
        {
            m_s2 = i;
            m_s2_pos = pos2.x()-m_cutBoxSet.at(m_s2).rect.left();
            return true;
        }
    }
    return false;
}
void ImageView::processPos2WhenDesc()
{
    //    printf("Desc \n");
    m_s2 = -2;
    m_s2_pos = -2;
    bool is_in_line = m_pos2_line%2==1 ? true: false;
    int line = m_pos2_line/2;

    if(is_in_line)
    {
        for (int i = 0; i < m_cutBoxSet.size(); i++)
        {
            if(line == m_cutBoxSet.at(i).line && m_pos2.x()<m_cutBoxSet.at(i).rect.right())
            {
                m_s2 = i;
                m_s2_pos = 0;
                break;
            }
            if(line < m_cutBoxSet.at(i).line)
            {
                m_s2 = i;
                m_s2_pos = 0;
                break;
            }
        }
        if(m_s2>m_s1)
        {
            m_s2 = m_s1;
            m_s2_pos = m_pos2.x()-m_cutBoxSet.at(m_s2).rect.left();
        }
    }
    else
    {
        for (int i = 0; i < m_cutBoxSet.size(); i++)
        {
            if(line == m_cutBoxSet.at(i).line)
            {
                m_s2 = i;
                m_s2_pos = 0;
                return;
            }
        }

    }
    if(m_s2 == -2)
    {
        m_s2 = 0;
        m_s2_pos = 0;
        //        printf("error\n");
    }
}

void ImageView::mouseMoveEvent(QMouseEvent *event)
{
    if (m_leftClick)
    {
        if(m_viewMode == LoadMode)
        {
            return;
        }
        if(m_viewMode == DragMode)
        {
            m_point = m_point + (event->pos() - m_lastPos) ;       //左上角的距离变化
        }
        m_lastPos = event->pos();
        if(m_viewMode == TextModeReady || m_viewMode == TextMode)
        {
            m_viewMode = TextMode;

            m_pos2 = QPoint((m_lastPos.x()-m_point.x())/m_scale, (m_lastPos.y()-m_point.y())/m_scale);
            m_pos2_line = getLineOfPos(m_pos2);
            //            printf("pos2:%d,%d",pos2.x(),pos2.y());

            bool isContained = processPos2IfContained(m_pos2);
            if(!isContained)
            {
                bool isAsc = comprePosition();
                if(isAsc)
                {
                    processPos2WhenAsc();
                }
                else
                {
                    processPos2WhenDesc();
                }
            }
        }
        update();
    }
}

